const {
	createBeanTable,
	analySaveData,
	analyGetDataById,
	analyUpateData,
	copyRowToBean,
	convertSearch,
	rowConvertToBean,
	convertInConditionParam,
	groupArray,
	getAllFieldName } = require('../ProxyBeanUtil')

class EntityProxy {

	bean;

	beanDefine;

	sqliteJdbc;

	constructor(bean,beanDefine,sqliteJdbc){
		this.bean = bean;
		this.beanDefine = beanDefine;
		this.sqliteJdbc = sqliteJdbc;
	}

	/**
	 * 保存对象
	 * 
	 * */
	async save(data,isBackEntity = true){
		const {sql,param,id} = analySaveData(this,data)
		await this.sqliteJdbc.run(sql,param)

		return isBackEntity ? await this.getById(id,isBackEntity) : {id};
	}

	/**
	 * 通过id获取数据
	 * 
	 * **/
	async getById(id,isUrgent=true){

		const {sql,param} = analyGetDataById(this,id)


		const rows = await this.sqliteJdbc.all(sql,param); 
		if(rows.length === 0)
			return null;

		const tbeans = await rowConvertToBean(this,rows,isUrgent);

		return tbeans[0];
	}

	/**
	 * 更新已经持久化的对象
	 * 
	 * */
	async update(tBean){

		if(!tBean.id)
			throw `update data must exist id property!`

		const oldData = await this.getById(tBean.id);

		//覆盖数据
		getAllFieldName(this).forEach(fieldName => {
			if(typeof tBean[fieldName] !== 'undefined'){
			 	oldData[fieldName] = tBean[fieldName];
			}
		})

		const {sql,param} = analyUpateData(this,oldData);


		await this.sqliteJdbc.run(sql,param)
	}

	/**
	 * 删除数据
	 * 
	 * */
	async remove(id){
		const sql = `DELETE FROM ${this.getTableName()} WHERE id=?;`;
		await this.sqliteJdbc.run(sql,[id])
	}


	/**
	 * 查询数据
	 * 
	 * */
	async find(searchData,isUrgent=true){
		const {sql,selectFields,param} = convertSearch(this,searchData);
		const rows = await this.sqliteJdbc.all(`SELECT ${selectFields} ${sql};`,param); 
		return await rowConvertToBean(this,rows,isUrgent);
	}

	/**
	 * 返回一条数据
	 * 
	 * */
	async findOne(searchData,isUrgent=true){
		const datas = await this.find(searchData,isUrgent)
		return datas.length >= 1 ? datas[0]:null;
	}

	/**
	 * 计算数量
	 * */
	async count(searchData){
		const {sql,param} = convertSearch(this,searchData);

		const [{count}] = await this.sqliteJdbc.all(`SELECT COUNT(*) AS count ${sql};`,param); 

		return count;
	}

	/**
	 * 分页查询
	 * */
	async findPagin(searchData,isUrgent=true){
		const {$pageSize=20,$curPage=1} = searchData; 

		searchData.$pageSize= $pageSize;
		searchData.$curPage = $curPage;
		searchData.$count = await this.count(searchData)

		const offset = ($curPage-1)*$pageSize;

		const {sql,selectFields,param} = convertSearch(this,searchData);
		const rows = await this.sqliteJdbc.all(`SELECT ${selectFields} ${sql} \nLIMIT ${$pageSize} OFFSET ${offset};`,param); 

		return await rowConvertToBean(this,rows,isUrgent);

	}

	/**
	 * 批量处理
	 * 
	 * */
	async _batchOperate(searchData,prefixSql,runParam=[]){
		//查询出所有的id
		const {sql,param} = convertSearch(this,searchData);
		const rows = await this.sqliteJdbc.all(`SELECT t.id ${sql};`,param);
		if(rows.length === 0)
			return 0;
		const removeIds = rows.map(v => v.id);

		const idsArray = groupArray(removeIds,20);

		for(let i = 0;i<idsArray.length;i++){
			//批量删除sql
			const batchSql = `${prefixSql} WHERE id in ${convertInConditionParam(idsArray[i])};`;
		
			await this.sqliteJdbc.run(batchSql,runParam)
		}

		return rows.length;
	}

	//批量删除
	async batchRemove(searchData){
		return await this._batchOperate(searchData,`DELETE FROM ${this.getTableName()}`);
	}

	//批量更新
	async batchUpdate(searchData,updateData){
		const setFields = [];
		const param = [];
		for(let p in updateData){
			setFields.push(`${p}=?`)
			param.push(updateData[p])
		}
		return await this._batchOperate(searchData,`UPDATE ${this.getTableName()} SET ${setFields.join(',')}`,param);
	}

	//获取表名
	getTableName(){
		return  this.beanDefine.getAnnotation('SqliteEntity').param.table || this.beanDefine.name 
	}

}

/**
 * 1.增强实体类
 * 2.自动创建表
 * 
 * */
//@Proxy(bean=SqliteEntity)
class SpringSqlite3Orm {

	//@Autowired
	springSqlite3Jdbc;

	log;

	//代理增强原始bean 返回代理bean 
	async doEnhance(bean,beanDefine){

		const log = this.log.method('doEnhance')

		const entityProxy = new EntityProxy(bean,beanDefine,this.springSqlite3Jdbc);
		
		//1.自动建表
		const tableSql = createBeanTable(entityProxy)

		await this.springSqlite3Jdbc.run(tableSql)

		return entityProxy;
	}

}



module.exports = {SpringSqlite3Orm,EntityProxy}